package threads;

import java.util.Hashtable;

import javax.swing.JOptionPane;

import server.ServerData;
import server.Session;
import connection.TCPSecureServerSocket;
import connection.exception.ConnectionResetException;
import messages.SignatureCheckRequestMessage;
import messages.SignatureCheckResponseMessage;
import messages.SignatureRegisterRequestMessage;
import messages.SignatureRegisterResponseMessage;

public class CertcopVericopConnection extends Thread {

	private TCPSecureServerSocket _tcpSocket;
	private Hashtable<Integer, Session> _sessionHandlers;
	private int _sessionNumber;
	private Object _lockingObject;

	public CertcopVericopConnection(TCPSecureServerSocket socket){
		_tcpSocket = socket;
		_sessionHandlers = new Hashtable<Integer, Session>();
		_sessionNumber = 0;

		_lockingObject = new Object();
	}

	public void run(){
		try {
			_tcpSocket.isVericop(true);
			_tcpSocket.waitChannelEstablishmentMode();
			
			if(!_tcpSocket.isSecureChannelEstablished()){
				JOptionPane.showMessageDialog(null, "Impossível estabelecer canal seguro com o servidor VERICOP");
				_tcpSocket.close();
				return;
			}

			while(ServerData.getServerData().isOnline()){
				// receive message here
			    Object msg = _tcpSocket.receive();

				//get session to which the message belongs
			    Integer sessionId = -1;
			    if (msg.getClass().getName().equals("messages.SignatureRegisterResponseMessage")) {
			        sessionId = ((SignatureRegisterResponseMessage) msg)._sessionID;
			    } else if(msg.getClass().getName().equals("messages.SignatureCheckResponseMessage")) {
			        sessionId = ((SignatureCheckResponseMessage) msg)._sessionID; 
			    }
			    Session sess = _sessionHandlers.get(sessionId);
			    
				//call add session message of the session to which message belongs
			    sess.addSessionMessage(msg);
			}

		} catch (ConnectionResetException e) {
			System.out.println("Ligação com o servidor VERICOP terminada.");
			_tcpSocket.close();
			return;
		}
	}

	public int sendCertcopRequest(Object obj) throws ConnectionResetException
	{
		synchronized(_lockingObject){
			Session sessionHandler;
			int sessionId = _sessionNumber++;

			if (_sessionHandlers.containsKey(sessionId))
				sessionHandler = _sessionHandlers.get(sessionId);
			else
			{
				sessionHandler = new Session(sessionId);
				_sessionHandlers.put(sessionId, sessionHandler);
			}

			// Add the session Id to the message
			if(obj.getClass().getName().equals("messages.SignatureRegisterRequestMessage")) {
			    SignatureRegisterRequestMessage t = (SignatureRegisterRequestMessage) obj;
			    t._sessionID = sessionId;
            } else if(obj.getClass().getName().equals("messages.SignatureCheckRequestMessage")) {
                SignatureCheckRequestMessage t = (SignatureCheckRequestMessage) obj;
                t._sessionID = sessionId;
			}
			
			_tcpSocket.send(obj);

			return sessionId;
		}
	}

	public Object receiveCertcopAnswer(int sessionId)
	{
		if (_sessionHandlers.containsKey(sessionId))
		{
			Session sessionHandler = _sessionHandlers.get(sessionId);
			return sessionHandler.getSessionMessage();
		}
		return null;
	}

}
